{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# bcolz memory profiling"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='go to index'></a>\n",
    "Index:\n",
    "  1. <a href='#Profiling carray'>Profiling carray</a>\n",
    "  -  <a href='#Profiling carray iterators'>Profiling carray iterators</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this part of the tutorial we will make use of the [ipython_memwatcher](https://github.com/FrancescAlted/ipython_memwatcher) to analyze the memory usage of the carray objects compared to Numpy arrays.\n",
    "\n",
    "Please be aware that measuring memory consumption is a tricky thing, so if you are going to run this section of the notebook several times you might need to restart the IPython kernel.\n",
    "If you see weird results or get confused, quit IPython and start a fresh shell; then run the fewest commands you need to understand how RAM is being used during the process."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='Profiling carray'></a>\n",
    "## Profiling carray\n",
    "<a href='#go to index'>Go to index</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from ipython_memwatcher import MemWatcher\n",
    "import numpy as np\n",
    "import bcolz\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [2] used 0.020 MiB RAM in 0.002s, peaked 0.000 MiB above current, total RAM usage 75.605 MiB\n"
     ]
    }
   ],
   "source": [
    "N = 1e8\n",
    "arange_results = {}\n",
    "mw = MemWatcher()\n",
    "mw.start_watching_memory()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's create a couple of big objects:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [3] used 762.973 MiB RAM in 0.390s, peaked 0.000 MiB above current, total RAM usage 838.578 MiB\n"
     ]
    }
   ],
   "source": [
    "numpy_array = np.arange(N)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [4] used 0.000 MiB RAM in 0.002s, peaked 0.000 MiB above current, total RAM usage 838.578 MiB\n"
     ]
    }
   ],
   "source": [
    "# Get some measurements from the last executed cell:\n",
    "arange_results['numpy'] = mw.measurements.memory_delta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [5] used 29.145 MiB RAM in 0.793s, peaked 0.000 MiB above current, total RAM usage 867.723 MiB\n"
     ]
    }
   ],
   "source": [
    "carray = bcolz.arange(N)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [6] used 0.000 MiB RAM in 0.002s, peaked 0.000 MiB above current, total RAM usage 867.723 MiB\n"
     ]
    }
   ],
   "source": [
    "# Get some measurements from the last executed cell:\n",
    "arange_results['carray in-memory'] = mw.measurements.memory_delta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [7] used 1.180 MiB RAM in 0.789s, peaked 0.000 MiB above current, total RAM usage 868.902 MiB\n"
     ]
    }
   ],
   "source": [
    "carray_disk = bcolz.arange(N, rootdir='mydir', mode='w')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [8] used 0.000 MiB RAM in 0.002s, peaked 0.000 MiB above current, total RAM usage 868.902 MiB\n"
     ]
    }
   ],
   "source": [
    "# Get some measurements from the last executed cell:\n",
    "arange_results['carray on-disk'] = mw.measurements.memory_delta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'numpy': 762.97265625, 'carray in-memory': 29.14453125, 'carray on-disk': 1.1796875}\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/faltet/miniconda/lib/python2.7/site-packages/IPython/core/interactiveshell.py:2885: FutureWarning: \n",
      "mpl_style had been deprecated and will be removed in a future version.\n",
      "Use `matplotlib.pyplot.style.use` instead.\n",
      "\n",
      "  exec(code_obj, self.user_global_ns, self.user_ns)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x7f04202d95d0>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/faltet/miniconda/lib/python2.7/site-packages/matplotlib/font_manager.py:1287: UserWarning: findfont: Font family [u'monospace'] not found. Falling back to Bitstream Vera Sans\n",
      "  (prop.get_family(), self.defaultFamily[fontext]))\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f04202fc8d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "mw.stop_watching_memory()\n",
    "\n",
    "d = arange_results\n",
    "print(d)\n",
    "\n",
    "arange_results_df = pd.DataFrame(arange_results.values(), index=arange_results.keys(), columns=['MiB'])\n",
    "arange_results_df.plot(kind='barh', figsize=(9,3), fontsize=16, title=\"arange RAM memory consumption\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this example, the numpy array consumes aproximately what we would expect ~760 MB  (N items x 8bytes x 2^-20 factor MB). Due to the nature of our data set, default compression does already a pretty neat job, and the ammount of memory required by this object is much smaller, around 26 MB.\n",
    "\n",
    "But a carray on-disk consumes only 0.2 MB, in this case our data resides on-disk using RAM only to keep references to that object, therefore as you see you can store huge amounts of information while treating them as if they were in-memory, carray on-disk and in-memory support exactly the same set of operations.\n",
    "\n",
    "Compression ratios will highly depend on your data set, in case your data set would be highly random and you could not get good compression ratios, you could always use carray on disk to use as much less RAM as possible."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='Profiling carray iterators'></a>\n",
    "## Profiling carray iterators\n",
    "<a href='#go to index'>Go to index</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's have a look now at some operations we already saw in this tutorial and check how much memory they actually consume:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [10] used 29.496 MiB RAM in 0.549s, peaked 0.000 MiB above current, total RAM usage 898.398 MiB\n"
     ]
    }
   ],
   "source": [
    "sumif_results = {}\n",
    "mw.start_watching_memory()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [11] used 2.227 MiB RAM in 26.273s, peaked 0.000 MiB above current, total RAM usage 900.625 MiB\n"
     ]
    }
   ],
   "source": [
    "r = sum(v for v in numpy_array if v < 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [12] used 0.113 MiB RAM in 0.001s, peaked 0.000 MiB above current, total RAM usage 900.738 MiB\n"
     ]
    }
   ],
   "source": [
    "# Get some measurements from the last executed cell:\n",
    "sumif_results['numpy'] = mw.measurements.memory_delta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [13] used 0.910 MiB RAM in 7.825s, peaked 1.625 MiB above current, total RAM usage 901.648 MiB\n"
     ]
    }
   ],
   "source": [
    "r =  sum(v for v in carray if v < 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [14] used 0.000 MiB RAM in 0.001s, peaked 0.000 MiB above current, total RAM usage 901.648 MiB\n"
     ]
    }
   ],
   "source": [
    "# Get some measurements from the last executed cell:\n",
    "sumif_results['carray in-memory'] = mw.measurements.memory_delta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [15] used 0.195 MiB RAM in 7.350s, peaked 1.867 MiB above current, total RAM usage 901.844 MiB\n"
     ]
    }
   ],
   "source": [
    "r =  sum(v for v in carray_disk if v < 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In [16] used 0.000 MiB RAM in 0.003s, peaked 0.000 MiB above current, total RAM usage 901.844 MiB\n"
     ]
    }
   ],
   "source": [
    "# Get some measurements from the last executed cell:\n",
    "sumif_results['carray on-disk'] = mw.measurements.memory_delta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'numpy': 2.2265625, 'carray in-memory': 0.91015625, 'carray on-disk': 0.1953125}\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x7f04202a0bd0>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f04aa6ef0d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "mw.stop_watching_memory()\n",
    "d = sumif_results\n",
    "print(d)\n",
    "\n",
    "sumif_df = pd.DataFrame(d.values(), index=d.keys(), columns=['MiB'])\n",
    "sumif_df.plot(kind='barh', figsize=(9,3), fontsize=16, title=\"sum-if RAM memory consumption\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When you iterate `carray` objects, the iterator in this run actually *releases* memory for the in-memory case, whereas the on-disk one does require very little (sometimes negative?), but YMMV.\n",
    "\n",
    "Again, measuring memory consumption is a tricky thing, so the take\n",
    "away message is that you should not be afraid of using iterators because they are 1) memory efficient and 2) they are *fast*."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## More about memory and other considerations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you want more info on other aspects of memory efficiency (and other optimization considerations) of bcolz, you can go to see [some tutorials](https://github.com/FrancescAlted/DataContainersTutorials) that I regularly teach in conferences around the world."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
